package com.zjh.simpledao.util;

import com.zjh.simpledao.annotation.Column;
import com.zjh.simpledao.annotation.Id;
import com.zjh.simpledao.annotation.Table;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 反射工具类
 *
 * @author zjh
 * @version V1.0.0
 * @date 2019/2/21 14:07
 * @since 1.0
 */
public class ReflectionUtil {

  /**
   * 获取表名称
   *
   * @param clazz
   * @return
   */
  public static String getTableName(Class clazz) {
    String result;
    Map<String, Object> reflectionMap = ResourceUtil.reflectionCache.get(clazz.getName());
    if (reflectionMap != null && !reflectionMap.isEmpty()) {
      result = (String) reflectionMap.get("getTableName");
      if (StringUtils.isNotEmpty(result)) {
        return result;
      }
    }
    boolean existTableAnno = clazz.isAnnotationPresent(Table.class);
    if (!existTableAnno) {
      throw new RuntimeException(clazz + " 没有Table注解.");
    }
    Table tableAnno = (Table) clazz.getAnnotation(Table.class);
    result = tableAnno.name();
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("getTableName", result);
    ResourceUtil.reflectionCache.put(clazz.getName(), map);
    return result;
  }

  /**
   * 获取主键名称
   *
   * @param clazz
   * @return
   */
  public static String getPkName(Class clazz) {
    String result;
    Map<String, Object> reflectionMap = ResourceUtil.reflectionCache.get(clazz.getName());
    if (reflectionMap != null && !reflectionMap.isEmpty()) {
      result = (String) reflectionMap.get("getPkName");
      if (StringUtils.isNotEmpty(result)) {
        return result;
      }
    }
    Field[] fields = clazz.getDeclaredFields();
    for (Field m : fields) {
      Id id = m.getAnnotation(Id.class);
      if (id != null) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("getPkName", id.name());
        ResourceUtil.reflectionCache.put(clazz.getName(), map);
        return id.name();
      }
    }
    return null;
  }

  /**
   * 获取Insert语句
   *
   * @param clazz
   * @return
   */
  public static String getInsertSqlFromIntity(Class clazz) {
    String result;
    Map<String, Object> reflectionMap = ResourceUtil.reflectionCache.get(clazz.getName());
    if (reflectionMap != null && !reflectionMap.isEmpty()) {
      result = (String) reflectionMap.get("getInsertSqlFromIntity");
      if (StringUtils.isNotEmpty(result)) {
        return result;
      }
    }
    StringBuffer sb = new StringBuffer();
    Field[] fields = clazz.getDeclaredFields();
    String tableName = ReflectionUtil.getTableName(clazz);
    List<String> col = new ArrayList<String>();
    List<String> param = new ArrayList<String>();
    for (int i = 0, len = fields.length; i < len; i++) {
      Column column = fields[i].getAnnotation(Column.class);
      if (column != null) {
        col.add(column.name());
        param.add("?");
      }
    }
    sb.append("insert into " + tableName);
    sb.append(" (" + StringUtils.join(col, ",") + ") values ");
    sb.append(" (" + StringUtils.join(param, ",") + ")");
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("getTableEntitySql", sb.toString());
    ResourceUtil.reflectionCache.put(clazz.getName(), map);
    return sb.toString();
  }
  /**
   * 获取update语句
   *
   * @param clazz
   * @return
   */
  public static String getUpdateSqlFromIntity(Class clazz) {
    String result;
    Map<String, Object> reflectionMap = ResourceUtil.reflectionCache.get(clazz.getName());
    if (reflectionMap != null && !reflectionMap.isEmpty()) {
      result = (String) reflectionMap.get("getUpdateSqlFromIntity");
      if (StringUtils.isNotEmpty(result)) {
        return result;
      }
    }
    StringBuffer sb = new StringBuffer();
    Field[] fields = clazz.getDeclaredFields();
    String tableName = ReflectionUtil.getTableName(clazz);
    List<String> col = new ArrayList<String>();
    List<String> param = new ArrayList<String>();
    for (int i = 0, len = fields.length; i < len; i++) {
      Column column = fields[i].getAnnotation(Column.class);
      if (column != null) {
        col.add(column.name());
        param.add("?");
      }
    }
    sb.append("update " + tableName + " set ");
    sb.append(StringUtils.join(col, "=?,") + "=? ");
    sb.append(" where " + getPkName(clazz) + "=?");
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("getUpdateSqlFromIntity", sb.toString());
    ResourceUtil.reflectionCache.put(clazz.getName(), map);
    return sb.toString();
  }
  /**
   * 获取delete语句
   *
   * @param clazz
   * @return
   */
  public static String getDeleteSqlFromIntity(Class clazz) {
    String result;
    Map<String, Object> reflectionMap = ResourceUtil.reflectionCache.get(clazz.getName());
    if (reflectionMap != null && !reflectionMap.isEmpty()) {
      result = (String) reflectionMap.get("getDeleteSqlFromIntity");
      if (StringUtils.isNotEmpty(result)) {
        return result;
      }
    }
    StringBuffer sb = new StringBuffer();
    Field[] fields = clazz.getDeclaredFields();
    String tableName = ReflectionUtil.getTableName(clazz);
    List<String> col = new ArrayList<String>();
    List<String> param = new ArrayList<String>();
    for (int i = 0, len = fields.length; i < len; i++) {
      Column column = fields[i].getAnnotation(Column.class);
      if (column != null) {
        col.add(column.name());
        param.add("?");
      }
    }
    sb.append("delete from " + tableName);
    sb.append(" where " + getPkName(clazz) + "=?");
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("getDeleteSqlFromIntity", sb.toString());
    ResourceUtil.reflectionCache.put(clazz.getName(), map);
    return sb.toString();
  }
  /**
   * 获取select语句
   *
   * @param clazz
   * @return
   */
  public static String getSelectSqlFromIntity(Class clazz) {
    String result;
    Map<String, Object> reflectionMap = ResourceUtil.reflectionCache.get(clazz.getName());
    if (reflectionMap != null && !reflectionMap.isEmpty()) {
      result = (String) reflectionMap.get("getSelectSqlFromIntity");
      if (StringUtils.isNotEmpty(result)) {
        return result;
      }
    }
    StringBuffer sb = new StringBuffer();
    Field[] fields = clazz.getDeclaredFields();
    String tableName = ReflectionUtil.getTableName(clazz);
    List<String> col = new ArrayList<String>();
    List<String> param = new ArrayList<String>();
    for (int i = 0, len = fields.length; i < len; i++) {
      Column column = fields[i].getAnnotation(Column.class);
      if (column != null) {
        col.add(column.name());
        param.add("?");
      }
    }
    sb.append("select * from  " + getTableName(clazz));
    sb.append(" where " + getPkName(clazz) + "=?");
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("getSelectSqlFromIntity", sb.toString());
    ResourceUtil.reflectionCache.put(clazz.getName(), map);
    return sb.toString();
  }

  /**
   * 根据实体获取列名
   *
   * @param clazz
   * @return
   */
  public static String getColumnlFromIntity(Class clazz) {
    String result;
    Map<String, Object> reflectionMap = ResourceUtil.reflectionCache.get(clazz.getName());
    if (reflectionMap != null && !reflectionMap.isEmpty()) {
      result = (String) reflectionMap.get("getColumnlFromIntity");
      if (StringUtils.isNotEmpty(result)) {
        return result;
      }
    }
    StringBuffer sb = new StringBuffer();
    Field[] fields = clazz.getDeclaredFields();
    String tableName = ReflectionUtil.getTableName(clazz);
    List<String> col = new ArrayList<String>();
    for (int i = 0, len = fields.length; i < len; i++) {
      Column column = fields[i].getAnnotation(Column.class);
      if (column != null) {
        col.add(column.name());
      }
    }
    sb.append(StringUtils.join(col, ","));
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("getColumnlFromIntity", sb.toString());
    ResourceUtil.reflectionCache.put(clazz.getName(), map);
    return sb.toString();
  }

  /**
   * 根据实体获取列名
   *
   * @param clazz
   * @return
   */
  public static List<String> getColumnlListFromIntity(Class clazz) {
    List<String> result;
    Map<String, Object> reflectionMap = ResourceUtil.reflectionCache.get(clazz.getName());
    if (reflectionMap != null && !reflectionMap.isEmpty()) {
      result = (List<String>) reflectionMap.get("getColumnlListFromIntity");
      if (result != null && !result.isEmpty()) {
        return result;
      }
    }
    Field[] fields = clazz.getDeclaredFields();
    String tableName = ReflectionUtil.getTableName(clazz);
    List<String> col = new ArrayList<String>();
    for (int i = 0, len = fields.length; i < len; i++) {
      Column column = fields[i].getAnnotation(Column.class);
      if (column != null) {
        col.add(column.name());
      }
    }
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("getColumnlListFromIntity", col);
    ResourceUtil.reflectionCache.put(clazz.getName(), map);
    return col;
  }

  /**
   * 根据实体获取列名
   *
   * @param clazz
   * @return
   */
  public static Map getMapColumnlLineFromIntity(Class clazz) {
    Map resultMap;
    Map<String, Object> reflectionMap = ResourceUtil.reflectionCache.get(clazz.getName());
    if (reflectionMap != null && !reflectionMap.isEmpty()) {
      resultMap = (Map) reflectionMap.get("getMapColumnlLineFromIntity");
      if (resultMap != null && !resultMap.isEmpty()) {
        return resultMap;
      }
    }
    Field[] fields = clazz.getDeclaredFields();
    String tableName = ReflectionUtil.getTableName(clazz);
    List<String> col = new ArrayList<String>();
    resultMap = new HashMap();
    for (int i = 0, len = fields.length; i < len; i++) {
      Column column = fields[i].getAnnotation(Column.class);
      if (column != null) {
        resultMap.put(column.name(), "");
      }
    }
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("getMapColumnlLineFromIntity", resultMap);
    ResourceUtil.reflectionCache.put(clazz.getName(), map);
    return resultMap;
  }
}
